home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_100
/
181_01
/
lzwunc.c
< prev
next >
Wrap
Text File
|
1985-03-09
|
4KB
|
148 lines
/* LZWUNC - FILE UNCOMPRESSOR UTILITY */
#include "stdio.h"
#include "fcntl.h"
#include "sgtty.h"
#include "debug.h"
#define FALSE 0
#define TRUE !FALSE
#define TABSIZE 4096
#define STACKSIZE TABSIZE
#define NO_PRED 0xFFFF
#define EMPTY 0xF000
#define NOT_FND 0xFFFF
#define NO_UPDATE FALSE
#define UEOF ((unsigned)EOF)
struct entry {
char used;
unsigned int next; /* hi bit is 'used' flag */
unsigned int predecessor; /* 12 bit code */
unsigned char follower;
} string_tab[TABSIZE];
char is_a_con = FALSE; /* suppresses printing dots during operation if
outfd is the console */
/* routines common to compress and decompress, contained in CommLZW.c */
unsigned hash();
unsigned unhash();
unsigned getcode();
putcode();
init_tab();
upd_tab();
main(argc,argv)
int argc; char *argv[];
{
register unsigned int c, tempc, code, oldcode, incode, finchar,lastchar;
char unknown = FALSE;
int code_count = TABSIZE - 256;
int infd, outfd;
register struct entry *ep;
if (3 != argc) {
fprintf(stderr,"Usage : lzwunc squeezefilename newfilename\n");
exit(0);
}
if ( -1 == (infd = open( *++argv, O_RDONLY )) ) {
fprintf(stderr,"Cant open %s\n", *argv);
exit(0);
}
if ( -1 == (outfd = creat(*++argv,0666)) ) {
fprintf(stderr,"Cant create %s\n",*argv);
exit(0);
}
is_a_con = isatty(outfd); /* suppress dots if it is */
init_tab(); /* set up atomic code definitions*/
code = oldcode = getcode(infd);
c = string_tab[code].follower; /* first code always known */
writec(outfd,c);
DEBUGGER(\
putc(c,stderr);\
fprintf(stderr,"\n%x\n",code);\
)
finchar = c;
while ( UEOF != (code = incode = getcode(infd)) ) {
DEBUGGER(fprintf(stderr,"\n%x\n",code);)
ep = &string_tab[code]; /* initialize pointer */
if ( !ep->used )
{ /* if code isn't known */
lastchar = finchar;
code = oldcode;
unknown = TRUE;
ep = &string_tab[code]; /* re-initialize pointer */
}
while (NO_PRED != ep->predecessor)
{
push( ep->follower); /* decode string backwards into */
/* stack */
code = ep->predecessor;
ep = &string_tab[code];
}
finchar = ep->follower;
/* above loop terminates, one way or another, with */
/* string_tab[code].follower = first char in string */
writec(outfd, finchar);
DEBUGGER(fputc(finchar,stderr);)
/* pop anything stacked during code parsing */
while ( EMPTY != (tempc = pop()) )
{
writec(outfd,tempc);
DEBUGGER(\
putc(tempc,stderr);\
)
}
if ( unknown ) { /* if code isn't known */
writec(outfd,finchar = lastchar); /* the follower char of last */
unknown = FALSE;
DEBUGGER(\
putc(lastchar,stderr);\
fprintf(stderr,"\nunknown code\n");\
)
}
if ( code_count )
{
upd_tab(oldcode,finchar);
--code_count;
DEBUGGER(fprintf(stderr,"\nAdding %x,%c = %x\n",\
oldcode,finchar,unhash(oldcode,finchar));)
}
oldcode = incode;
}
flushout(outfd); /* write out fractional buffer, if any */
exit(0); /* close all files and quit */
}
char stack[STACKSIZE]; /* stack for pushing and popping characters */
int sp = 0; /* current stack pointer */
push(c)
int c;
{
stack[sp] = ((char) c);/* coerce passed integer into a character */
++sp;
if (sp >= STACKSIZE) {
fprintf(stderr,"Stack overflow, aborting\n");
exit(1); /* non-0 exit parameter terminates batch job */
}
}
pop()
{
if (sp > 0)
{
--sp; /* push leaves sp pointing to next empty slot */
return ( (int) stack[sp] ); /* make sure pop returns char */
}
else
return EMPTY;
}